/**
 * \file devices.hpp
 * \brief Parallel and roundrobin device definitions headerfile
 * \author Wouter Caarls <w.caarls@tudelft.nl> 
 *
 * \verbatim
 * Copyright (c) 2005-7 Wouter Caarls, Delft University of Technology
 * 
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 * \endverbatim
 */

#include <vector>

#include "des.hpp"

class DESparallelDevice : public virtual DESdevice
{
public:
  DESparallelDevice(std::string name="unnamed") : DESdevice(name) { }

  void addProcess(DESprocess* process);
  void processEvent(DESevent event);

  DESevent wait(class DESprocess *process, class DESsignal* signal);
  DESevent wait(class DESprocess *process, TIME time);
  void exit(class DESprocess *process);

public:
  std::vector<DESprocess*> m_processes;
};

class DESthread : public DESprocess
{
public:
  typedef enum {StateNew, StateRunnable, StateRunning, StateWaiting, StateZombie} StateType;

public:
  DESthread(std::string name, void *argument=NULL);
  
  virtual void main(void *argument) = 0;
  DESevent sleep(TIME time);
  DESevent yield() { return sleep(0); }

public:
  class DESroundRobinDevice *m_rrDevice;
  StateType                  m_state;
  int                        m_id;
};

std::ostream& operator<<(std::ostream &s, DESthread::StateType t);

class DESroundRobinDevice : public virtual DESdevice
{
public:
  DESroundRobinDevice(std::string name="unnamed") : DESdevice(name), m_currentProcess(-1), m_processedTime(0), m_lastProcessTime(0) { }

  void addProcess(DESthread* process);
  void processEvent(DESevent event);

  DESevent wait(class DESprocess *process, class DESsignal* signal);
  DESevent wait(class DESprocess *process, TIME time);
  void exit(class DESprocess *process);

  DESevent sleep(class DESthread *process, TIME time);

  TIME getProcessedTime() { return m_processedTime; }

public:
  int m_currentProcess;
  std::vector<DESthread*> m_processes;

private:
  TIME m_processedTime;
  TIME m_lastProcessTime;
};
